﻿/*
    This file is part of nDoctor Light

    NDoctor is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    NDoctor is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with NDoctor.  If not, see <http://www.gnu.org/licenses/>.
*/
namespace Probel.Ldoc.Stat
{
    using System;
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;

    using log4net;

    using NHibernate;

    using Probel.Ldoc.Stat.Entities;
    using Probel.Ldoc.Stat.Helpers;
    using Probel.Ldoc.Stat.Orm;

    /// <summary>
    /// This class logs all the activities and will store it when it is closed
    /// </summary>
    public class StatLogger
    {
        #region Fields

        private static readonly Session AppSession = new Session();

        private readonly Guid ApplicationId;
        private readonly ISessionFactory Factory;
        private readonly ILog Logger = LogManager.GetLogger(LogHelper.Name);

        private List<Activity> Activities = new List<Activity>();

        #endregion Fields

        #region Constructors

        internal StatLogger(Application application, string version, ISessionFactory factory, DateTime sessionStart)
        {
            AppSession.Start = sessionStart;
            AppSession.Version = version;
            this.ApplicationId = application.Id;
            this.Factory = factory;
        }

        #endregion Constructors

        #region Methods

        /// <summary>
        /// Closes the logger and save the statistics into the repository.
        /// This method is run asynchronously
        /// </summary>
        public void Close()
        {
            AppSession.End = DateTime.Now.ToUniversalTime();

            using (var session = this.Factory.OpenSession())
            {
                AppSession.Application = session.Get<Application>(this.ApplicationId);
                AppSession.Application.Sessions.Add(AppSession);

                foreach (var activity in Activities) { activity.Application = AppSession.Application; }
                AppSession.Activities = Activities;

                session.SaveOrUpdate(AppSession);
                session.Flush();

                this.Logger.Debug("Statistics closed");
            }
        }

        /// <summary>
        /// Logs the specified activity.
        /// </summary>
        /// <param name="activity">The activity.</param>
        public void Log(Activity activity)
        {
            Activities.Add(activity);
        }

        #endregion Methods
    }
}